package com.pansoft.hd.multisig;

import com.alibaba.fastjson.JSONArray;
import com.efounder.chat.http.JFCommonRequestManager;
import com.efounder.common.TCommonRequestManager;
import com.efounder.utils.ResStringUtil;
import com.pansoft.hd.model.MultiSignCommonOwnerInfo;
import com.pansoft.openplanet.R;
import com.pansoft.openplanet.constant.IPAssetsConstant;
import com.pansoft.openplanet.util.TCRequestUtil;

import org.json.JSONObject;
import org.web3j.abi.FunctionEncoder;
import org.web3j.abi.TypeReference;
import org.web3j.abi.datatypes.Function;
import org.web3j.abi.datatypes.Type;
import org.web3j.abi.datatypes.generated.Uint256;
import org.web3j.crypto.Credentials;
import org.web3j.crypto.Hash;
import org.web3j.crypto.RawTransaction;
import org.web3j.crypto.Sign;
import org.web3j.crypto.TransactionEncoder;
import org.web3j.utils.Convert;
import org.web3j.utils.Numeric;

import java.math.BigInteger;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;

import okhttp3.Response;

import static org.web3j.tx.Contract.GAS_LIMIT;

/**
 * ETH多重签名工具创建以及交易
 * Created by yqs
 * Date: 2019/11/7
 * Time: 14:58
 */
public class ETHMultiSignManager {


    /**
     * 创建eth多签钱包
     *
     * @param addresssList 共同拥有人地址列表
     * @param m            满足m 人签名即可进行交易
     * @param credentials  发起创建钱包用户证书
     * @param nonce        发起创建钱包的用户nonce值
     * @param chainId      链id
     * @return hexValue 签名数据
     */
    public String createMultiSignWallet(List<String> addresssList, BigInteger m, Credentials credentials, BigInteger nonce, int chainId) {
        String encodedConstructor = FunctionEncoder
                .encodeConstructor(Arrays.<Type>asList(new Uint256(m),
                        new org.web3j.abi.datatypes.DynamicArray<org.web3j.abi.datatypes.Address>(
                                org.web3j.abi.Utils.typeMap(addresssList, org.web3j.abi.datatypes.Address.class))));
        String data = "0x60806040523480156200001157600080fd5b506040516200121e3803806200121e83398101806040528101908080519060200190929190805182019291905050506000600a82511115801562000056575081518311155b801562000064575060008314155b15156200007057600080fd5b600090505b8151811015620001c757600073ffffffffffffffffffffffffffffffffffffffff168282815181101515620000a657fe5b9060200190602002015173ffffffffffffffffffffffffffffffffffffffff16141580156200013d575060001515600260008484815181101515620000e757fe5b9060200190602002015173ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff161515145b15156200014957600080fd5b60016002600084848151811015156200015e57fe5b9060200190602002015173ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006101000a81548160ff021916908315150217905550808060010191505062000075565b8160039080519060200190620001df929190620001f0565b5082600181905550505050620002c5565b8280548282559060005260206000209081019282156200026c579160200282015b828111156200026b5782518260006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055509160200191906001019062000211565b5b5090506200027b91906200027f565b5090565b620002c291905b80821115620002be57600081816101000a81549073ffffffffffffffffffffffffffffffffffffffff02191690555060010162000286565b5090565b90565b610f4980620002d56000396000f300608060405260043610610078576000357c0100000000000000000000000000000000000000000000000000000000900463ffffffff16806329e33647146100e557806342cde4e81461025c57806369fcba7714610287578063722713f7146103e3578063aa5df9e21461040e578063affed0e01461047b575b7fd241e73300212f6df233a8e6d3146b88a9d4964e06621d54b5ff6afeba7b1b883334604051808373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020018281526020019250505060405180910390a1005b3480156100f157600080fd5b5061023f600480360381019080803590602001908201803590602001908080602002602001604051908101604052809392919081815260200183836020028082843782019150505050505091929192908035906020019082018035906020019080806020026020016040519081016040528093929190818152602001838360200280828437820191505050505050919291929080359060200190820180359060200190808060200260200160405190810160405280939291908181526020018383602002808284378201915050505050509192919290803573ffffffffffffffffffffffffffffffffffffffff16906020019092919080359060200190929190803590602001908201803590602001908080601f01602080910402602001604051908101604052809392919081815260200183838082843782019150505050505091929192905050506104a6565b604051808381526020018281526020019250505060405180910390f35b34801561026857600080fd5b50610271610903565b6040518082815260200191505060405180910390f35b34801561029357600080fd5b506103e1600480360381019080803590602001908201803590602001908080602002602001604051908101604052809392919081815260200183836020028082843782019150505050505091929192908035906020019082018035906020019080806020026020016040519081016040528093929190818152602001838360200280828437820191505050505050919291929080359060200190820180359060200190808060200260200160405190810160405280939291908181526020018383602002808284378201915050505050509192919290803573ffffffffffffffffffffffffffffffffffffffff16906020019092919080359060200190929190803590602001908201803590602001908080601f0160208091040260200160405190810160405280939291908181526020018383808284378201915050505050509192919290505050610909565b005b3480156103ef57600080fd5b506103f8610eba565b6040518082815260200191505060405180910390f35b34801561041a57600080fd5b5061043960048036038101908080359060200190929190505050610ed9565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b34801561048757600080fd5b50610490610f17565b6040518082815260200191505060405180910390f35b6000806000606060008060006001548c511415156104c357600080fd5b8a518c511480156104d557508c518c51145b15156104e057600080fd5b60197f01000000000000000000000000000000000000000000000000000000000000000260007f010000000000000000000000000000000000000000000000000000000000000002308c8c8c60005460405180887effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff19167effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff19168152600101877effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff19167effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff191681526001018673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166c010000000000000000000000000281526014018573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166c0100000000000000000000000002815260140184815260200183805190602001908083835b602083101515610680578051825260208201915060208101905060208303925061065b565b6001836020036101000a038019825116818451168082178552505050505050905001828152602001975050505050505050604051809103902094506040805190810160405280601c81526020017f19457468657265756d205369676e6564204d6573736167653a0a3332000000008152509350600092505b6001548310156108e45783856040518083805190602001908083835b6020831015156107395780518252602082019150602081019050602083039250610714565b6001836020036101000a038019825116818451168082178552505050505050905001826000191660001916815260200192505050604051809103902091506001828e8581518110151561078857fe5b906020019060200201518e868151811015156107a057fe5b906020019060200201518e878151811015156107b857fe5b90602001906020020151604051600081526020016040526040518085600019166000191681526020018460ff1660ff1681526020018360001916600019168152602001826000191660001916815260200194505050505060206040516020810390808403906000865af1158015610833573d6000803e3d6000fd5b505050602060405103519050600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff16141580156108cc575060011515600260008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff161515145b15156108d757600080fd5b82806001019350506106f8565b6001600054019650600180540195505050505050965096945050505050565b60015481565b60006060600080600060011515600260003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff16151514151561097157600080fd5b6001548a5114151561098257600080fd5b88518a5114801561099457508a518a51145b151561099f57600080fd5b60197f01000000000000000000000000000000000000000000000000000000000000000260007f010000000000000000000000000000000000000000000000000000000000000002308a8a8a60005460405180887effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff19167effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff19168152600101877effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff19167effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff191681526001018673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166c010000000000000000000000000281526014018573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166c0100000000000000000000000002815260140184815260200183805190602001908083835b602083101515610b3f5780518252602082019150602081019050602083039250610b1a565b6001836020036101000a038019825116818451168082178552505050505050905001828152602001975050505050505050604051809103902094506040805190810160405280601c81526020017f19457468657265756d205369676e6564204d6573736167653a0a3332000000008152509350600092505b600154831015610da35783856040518083805190602001908083835b602083101515610bf85780518252602082019150602081019050602083039250610bd3565b6001836020036101000a038019825116818451168082178552505050505050905001826000191660001916815260200192505050604051809103902091506001828c85815181101515610c4757fe5b906020019060200201518c86815181101515610c5f57fe5b906020019060200201518c87815181101515610c7757fe5b90602001906020020151604051600081526020016040526040518085600019166000191681526020018460ff1660ff1681526020018360001916600019168152602001826000191660001916815260200194505050505060206040516020810390808403906000865af1158015610cf2573d6000803e3d6000fd5b505050602060405103519050600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1614158015610d8b575060011515600260008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff161515145b1515610d9657600080fd5b8280600101935050610bb7565b8773ffffffffffffffffffffffffffffffffffffffff16878760405180828051906020019080838360005b83811015610de9578082015181840152602081019050610dce565b50505050905090810190601f168015610e165780820380516001836020036101000a031916815260200191505b5091505060006040518083038185875af1925050501515610e3657600080fd5b6001600054016000819055507fc95f8b91b103304386b955ef73fadac189f8ad66b33369b6c34a17a60db7bd0a8888604051808373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020018281526020019250505060405180910390a15050505050505050505050565b60003073ffffffffffffffffffffffffffffffffffffffff1631905090565b600381815481101515610ee857fe5b906000526020600020016000915054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b600054815600a165627a7a723058209f380c65c1f4527bb6ce9dd3defb142e7df84c406bd32ed0545b3a09e623260f0029";
        data += encodedConstructor;
        //这个值的含义是创建合约时直接给合约多少以太币 所以写0
        BigInteger value = Convert.toWei("0", Convert.Unit.ETHER).toBigInteger();
        //创建交易 默认手续费32gwei
        //gas GAS_PRICE
        BigInteger gasPrice = BigInteger.valueOf(32_000_000_000L);

        RawTransaction rawTransaction = RawTransaction.createContractTransaction(nonce, gasPrice, GAS_LIMIT,
                value, data);
        // 签名Transaction
        byte[] signedMessage;
        if (chainId == IPAssetsConstant.CHAIN_ID_ETE) {
            //ete需要chainid
            signedMessage = TransactionEncoder.signMessage(rawTransaction, IPAssetsConstant.CHAIN_ID_ETE, credentials);
        } else {
            signedMessage = TransactionEncoder.signMessage(rawTransaction, credentials);
        }
        //签名16进制数据
        String hexValue = Numeric.toHexString(signedMessage);
        return hexValue;
    }


    /**
     * 多签钱包上传服务器
     *
     * @param signHexValue  签名信息
     * @param m             最小确认数
     * @param n             共同持有人的数量
     * @param chainId       链id
     * @param walletIcon    钱包头像
     * @param walletName    钱包名称
     * @param ownerInfoList 共同持有人信息
     * @param tag           activity的tag
     * @param reqCallBack   回调
     */
    public void addETHMultisigWalletToServer(String signHexValue, String m, int n, int chainId, String walletIcon,
                                             String walletName, ArrayList<MultiSignCommonOwnerInfo> ownerInfoList, String tag, TCommonRequestManager.ReqCallBack reqCallBack) {
        HashMap<String, String> paramMap = new HashMap<>();
        paramMap.put("chainID", chainId + "");
        paramMap.put("m", m + "");
        paramMap.put("n", n + "");
        paramMap.put("name", walletName);
        paramMap.put("icon", walletIcon == null ? "" : walletIcon);
        paramMap.put("hexValue", signHexValue);
        paramMap.put("ethMultiSigWalletDetails", JSONArray.toJSONString(ownerInfoList));

        String requestUrl = TCRequestUtil.BASE_URL + "/ethMultiSig/addETHWallet";
        JFCommonRequestManager.getInstance().requestPostByAsyn(tag, requestUrl, paramMap, reqCallBack);
    }


    /**
     * 获取多签钱包合约地址的交易nonce
     * createTransaction 方法的nonce 需要通过这个方法获取
     *
     * @param chainId         链id
     * @param contractAddress 钱包地址（也就是合约地址）
     * @param requestAddress  请求者的地址 也就是自己的钱包地址 暂时不用写死了
     * @return
     */
    public BigInteger getContractAddressNonce(String tag, int chainId, String contractAddress, String requestAddress) throws Exception {
        HashMap<String, String> paramMap = new HashMap<>();
        paramMap.put("chainID", chainId + "");
        paramMap.put("contractAddress", contractAddress);
//        paramMap.put("callerAddress", requestAddress);
        paramMap.put("callerAddress", "0x5941166c7db099173a293e5711a57c8b81351fb1");
        String requestUrl = TCRequestUtil.BASE_URL + "/ethMultiSig/getETHWalletNonce";
        Response response = JFCommonRequestManager.getInstance().requestPostBySyn(tag, requestUrl, paramMap);
        if (response != null && response.isSuccessful()) {
            String result = response.body().string();
            JSONObject jsonObject = new JSONObject(result);
            if (jsonObject.optString("result", "").equals("success")) {
                return new BigInteger(jsonObject.optString("ETHWalletNonce", "0"));
            }
            throw new Exception("获取nonce失败");
        } else {
            throw new Exception("获取nonce失败");
        }
    }

    /**
     * 获取以太坊多重钱包余额
     *
     * @param tag
     * @param chainId         链id
     * @param contractAddress 钱包地址（也就是合约地址）
     * @return
     * @throws Exception
     */
    public BigInteger getMultiSigWalletBalance(String tag, int chainId, String contractAddress) throws Exception {
        HashMap<String, String> paramMap = new HashMap<>();
        paramMap.put("chainID", chainId + "");
        paramMap.put("contractAddress", contractAddress);
        //这个地址可以随便写
        paramMap.put("callerAddress", "0x5941166c7db099173a293e5711a57c8b81351fb1");
        String requestUrl = TCRequestUtil.BASE_URL + "/ethMultiSig/getETHWalletBalance";
        Response response = JFCommonRequestManager.getInstance().requestPostBySyn(tag, requestUrl, paramMap);
        if (response != null && response.isSuccessful()) {
            String result = response.body().string();
            JSONObject jsonObject = new JSONObject(result);
            if (jsonObject.optString("result", "").equals("success")) {
                return new BigInteger(jsonObject.optString("ETHWalletBalance", "0"));
            }
            throw new Exception("获取余额失败");
        } else {
            throw new Exception("获取余额失败");
        }

    }

    /**
     * 创建多签交易
     *
     * @param contractAddress    多签钱包地址
     * @param destinationAddress 收款地址
     * @param amount             转账金额 注意单位！！ 输入  Convert.toWei(amountOfMoney, Convert.Unit.ETHER).toBigInteger();
     *                           //@param data               固定传 0x
     * @param nonce              多签钱包合约地址的交易nonce
     * @param credentials        共同拥有者中自己钱包的 credentials
     */
    public HashMap createTransaction(String contractAddress, String destinationAddress, BigInteger amount,
                                     BigInteger nonce, Credentials credentials) {
        //data 暂时固定传这个
        String data = "0x";
        String sha3Hash = getSha3Hash(contractAddress, destinationAddress, amount, data, nonce);
        HashMap hashMap = signHash3ByCredentials(sha3Hash, credentials);
        hashMap.put("sha3", sha3Hash);
        return hashMap;
    }


    /**
     * Hash.sha3(待签名数据)
     *
     * @param contractAddress 合约钱包地址
     * @param receiveAddress  收款人地址
     * @param amount          交易金额
     * @param data            固定传 0x
     * @param nonce           合约地址的交易nonce
     * @return
     * @throws Exception
     */
    public String getSha3Hash(String contractAddress, String receiveAddress, BigInteger amount, String data, BigInteger nonce) {
        String message = "0x1900" + contractAddress.substring(2) + receiveAddress.substring(2)
                + Numeric.toHexStringNoPrefixZeroPadded(amount, 64) + data.substring(2)
                + Numeric.toHexStringNoPrefixZeroPadded(nonce, 64);
        return Hash.sha3(message);
    }

    /**
     * 使用credentials 对hashSha3 签名
     * 使用在需要确认交易的人调用
     *
     * @param hashSha3
     * @param credentials
     */
    public HashMap signHash3ByCredentials(String hashSha3, Credentials credentials) {
        byte[] hashSha3Bytes = Numeric.hexStringToByteArray(hashSha3);
        Sign.SignatureData signature1 = Sign.signPrefixedMessage(hashSha3Bytes, credentials.getEcKeyPair());

        HashMap<String, String> signMap = new HashMap<>();

        BigInteger sigv = Numeric.toBigInt(signature1.getV());
        String sigr = Numeric.toHexString(signature1.getR());
        String sigs = Numeric.toHexString(signature1.getS());

        signMap.put("sigv", sigv.toString());
        signMap.put("sigr", sigr);
        signMap.put("sigs", sigs);

        return signMap;
    }


    /**
     * 发起交易
     * 某个人要花多签钱包的钱
     *
     * @param ethMultiSigWalletId 多签钱包编号（服务器返回）
     * @param from                交易发起者的钱包地址
     * @param receiveAddress      收款地址
     * @param chainId             链id
     * @param amount              转账金额
     * @param v                   hashsha3 签名后的  v
     * @param r                   hashsha3 签名后的  r
     * @param s                   hashsha3 签名后的  s
     * @param sha3                hashsha3待签名数据
     * @return
     */
    public String startTransactinToServer(String tag, String ethMultiSigWalletId, String from, String receiveAddress, int chainId, String amount, String v, String r, String s, String sha3) throws Exception {
        HashMap<String, String> paramMap = new HashMap<>();
        paramMap.put("ethMultisigWalletId", ethMultiSigWalletId + "");
        paramMap.put("from", from);
        paramMap.put("destination", receiveAddress);
        paramMap.put("chainId", chainId + "");
        paramMap.put("value", amount);
        paramMap.put("v", v);
        paramMap.put("r", r);
        paramMap.put("s", s);
        paramMap.put("sha3", sha3);

        String requestUrl = TCRequestUtil.BASE_URL + "/ethMultiSig/transaction";
        Response response = JFCommonRequestManager.getInstance().requestPostBySyn(tag, requestUrl, paramMap);
        if (response != null && response.isSuccessful()) {
            String result = response.body().string();
            return result;
        } else {
            throw new Exception(ResStringUtil.getString(R.string.common_text_http_request_fail_abnormal));
        }
    }

    /**
     * 共同持有者确认交易后发送到服务器
     *
     * @param tag
     * @param from 交易确认者的钱包地址
     * @param v
     * @param r
     * @param s
     * @param txId 交易id
     * @return
     */
    public String sendTradeSignatureToServer(String tag, String ethMultiSigWalletId, String from, String v, String r, String s, String txId) throws Exception {
        HashMap<String, String> paramMap = new HashMap<>();
        paramMap.put("from", from);

        paramMap.put("v", v);
        paramMap.put("r", r);
        paramMap.put("s", s);
        paramMap.put("txId", txId);

        String requestUrl = TCRequestUtil.BASE_URL + "/ethMultiSig/sendSignature";
        Response response = JFCommonRequestManager.getInstance().requestPostBySyn(tag, requestUrl, paramMap);
        if (response != null && response.isSuccessful()) {
            String result = response.body().string();
            return result;
        } else {
            throw new Exception(ResStringUtil.getString(R.string.common_text_http_request_fail_abnormal));
        }
    }

    /**
     * 最终确认交易
     * * 当签名人数达到最小确认数的时候，通知发起交易的人最终确认交易，需要调用这个方法
     *
     * @param tag
     * @param txId     交易id
     * @param chainId  链id
     * @param signData 签名数据
     */
    public String confirmTransactionToServer(String tag, String txId, int chainId, String signData) throws Exception {
        HashMap<String, String> paramMap = new HashMap<>();
        paramMap.put("signData", signData);
        paramMap.put("chainId", chainId + "");
        paramMap.put("txId", txId);

        String requestUrl = TCRequestUtil.BASE_URL + "/ethMultiSig/confirmTransaction";
        Response response = JFCommonRequestManager.getInstance().requestPostBySyn(tag, requestUrl, paramMap);
        if (response != null && response.isSuccessful()) {
            String result = response.body().string();
            return result;
        } else {
            throw new Exception(ResStringUtil.getString(R.string.common_text_http_request_fail_abnormal));
        }
    }


    /**
     * 最终进行交易确认的人签名
     *
     * @param chainId         链id
     * @param nonce           当前签名的人地址的 交易nonce
     * @param amount          交易金额 0.01
     * @param receiveAddress  收款人
     * @param contractAddress 合约钱包地址
     * @param credentials     证书授权
     * @param sigvList
     * @param sigrList
     * @param sigsList
     * @return
     */
    public String signConfirmTransaction(int chainId, String nonce, String amount, String receiveAddress, String contractAddress,
                                         Credentials credentials, List<BigInteger> sigvList, List<byte[]> sigrList, List<byte[]> sigsList) {


        BigInteger value = Convert.toWei(amount, Convert.Unit.ETHER).toBigInteger();
        Function function = new Function("executeTransfer", Arrays.<Type>asList(
                new org.web3j.abi.datatypes.DynamicArray<org.web3j.abi.datatypes.generated.Uint8>(
                        org.web3j.abi.Utils.typeMap(sigvList, org.web3j.abi.datatypes.generated.Uint8.class)),
                new org.web3j.abi.datatypes.DynamicArray<org.web3j.abi.datatypes.generated.Bytes32>(
                        org.web3j.abi.Utils.typeMap(sigrList, org.web3j.abi.datatypes.generated.Bytes32.class)),
                new org.web3j.abi.datatypes.DynamicArray<org.web3j.abi.datatypes.generated.Bytes32>(
                        org.web3j.abi.Utils.typeMap(sigsList, org.web3j.abi.datatypes.generated.Bytes32.class)),
                new org.web3j.abi.datatypes.Address(receiveAddress), new Uint256(value),
                new org.web3j.abi.datatypes.DynamicBytes(Numeric.hexStringToByteArray("0x"))),
                Collections.<TypeReference<?>>emptyList());
        String functionData = FunctionEncoder.encode(function);
        //gasprice 默认为22Gwei 我们设置高一些
        BigInteger gasPrice = BigInteger.valueOf(32_000_000_000L);
        RawTransaction rawTransaction = RawTransaction.createTransaction(new BigInteger(nonce), gasPrice, GAS_LIMIT, contractAddress,
                functionData);
        // 签名Transaction，这里要对交易做签名
        byte[] signedMessage;
        if (chainId == IPAssetsConstant.CHAIN_ID_ETE) {
            //ete需要chainid
            signedMessage = TransactionEncoder.signMessage(rawTransaction, IPAssetsConstant.CHAIN_ID_ETE, credentials);
        } else {
            signedMessage = TransactionEncoder.signMessage(rawTransaction, credentials);
        }
        String hexValue = Numeric.toHexString(signedMessage);
        return hexValue;
    }
}
